﻿using System;
using System.Web.Mvc;
using System.Web.Mvc.Async;

using ControllersCache = Sencha.ReaderWriterLockCache<System.Type, Sencha.Direct.Api.ControllerDescription>;
using ActionsCache = Sencha.ReaderWriterLockCache<System.Web.Mvc.ActionDescriptor, Sencha.Direct.Api.ActionDescription>;

namespace Sencha.Direct.Api
{
	public sealed class DescriptionCache
	{
		private static readonly ControllersCache s_Controllers = new ControllersCache(40);
		private static readonly ActionsCache s_Actions = new ActionsCache(200);

		public static ControllerDescription GetControllerDescription(Type controllerType)
		{
			if (controllerType == null)
				throw new ArgumentNullException("controllerType");
			if (!typeof(Controller).IsAssignableFrom(controllerType))
				throw new ArgumentException();

			var cachedDescr = s_Controllers.FetchOrCreateValue(controllerType, () =>
			{
				var descriptor = (ControllerDescriptor)new ReflectedControllerDescriptor(controllerType);

				var description = new ControllerDescription(descriptor);
				return description;
			});

			return cachedDescr;
		}
		internal static ActionDescription GetActionDescription(ActionDescriptor actionDescriptor)
		{
			if (actionDescriptor == null)
				throw new ArgumentNullException("actionDescriptor");

			var controllerDescription = GetControllerDescription(actionDescriptor.ControllerDescriptor.ControllerType);

			var cachedDescr = s_Actions.FetchOrCreateValue(actionDescriptor, () =>
			{
				var description = new ActionDescription(controllerDescription, actionDescriptor);
				return description;
			});

			return cachedDescr;
			
		}
		internal static void PutActionDescription(ActionDescriptor descriptor, ActionDescription description)
		{
			if (descriptor == null)
				throw new ArgumentNullException("descriptor");
			if (description == null)
				throw new ArgumentNullException("description");

			s_Actions.ExchangeValue(descriptor, description);
		}
	}
}
